﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;
using SimpleServiceBus.Bus;
using SimpleServiceBus.Bus.MessageManagement.MessageHandling;
using SimpleServiceBus.Bus.Pipeline;
using SimpleServiceBus.Bus.Pipeline.PipelineComponents;
using SimpleServiceBus.Bus.Pipeline.PipelineComponents.MessageFiltering;
using SimpleServiceBus.Bus.Pipeline.PipelineComponents.MessageLogging;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Tests.Bus.MessageManagement.MessageHandling;
using SimpleServiceBus.Tests.Stubs;
using SimpleServiceBus.Utilities.ObjectBuilder;

namespace SimpleServiceBus.Tests.Bus.Pipeline
{
    [TestFixture]
    public class DefaultMessagePipelineFactoryTestFixture
    {
        private IMessagingEndpoint _endpoint;
        private EndpointServiceManager _services;
       

        [TestFixtureSetUp]
        public void SetUp()
        {
            _endpoint = MockRepository.GenerateStub<IMessagingEndpoint>();
            _services = new EndpointServiceManager(_endpoint);
            _services.RegisterService<IObjectBuilderService>(new DefaultObjectBuilderService());
            _services.RegisterService<IMessagePipelineFactory>(new DefaultMessagePipelineFactory());
            _services.Start();
        }

        [Test]
        public void Can_Create_Send_And_Receive_Pipelines()
        {
            var factory = _services.GetService<IMessagePipelineFactory>();
            _endpoint.Stub(action => action.LocalServices).Return(_services);

            var pipeline = factory.CreatePipelineFor(new MessageEnvelope(), PipelineDirection.Receive);
            Assert.That(pipeline.PipelineDirection, Is.EqualTo(PipelineDirection.Receive));


            _endpoint.Stub(action => action.LocalServices).Return(_services);
            pipeline = factory.CreatePipelineFor(new MessageEnvelope(), PipelineDirection.Send);
            Assert.That(pipeline.PipelineDirection, Is.EqualTo(PipelineDirection.Send));

            MessagePipeline.ClearCurrentPipeline(PipelineDirection.Receive);
            MessagePipeline.ClearCurrentPipeline(PipelineDirection.Send);

        }

        [Test]
        public void Pipelines_Are_Initialized_With_Appropriate_Default_Components()
        {
            var env = new MessageEnvelope {Body = Guid.NewGuid()};
            var factory = _services.GetService<IMessagePipelineFactory>();
            _endpoint.Stub(action => action.LocalServices).Return(_services);

            var pipeline = factory.CreatePipelineFor(env, PipelineDirection.Receive);
            Assert.That(pipeline.PipelineComponents.Count,Is.EqualTo(6));
            Assert.That(pipeline.PipelineComponents[0],Is.TypeOf(typeof(MessageBodySerializationComponent )));
            Assert.That(pipeline.PipelineComponents[1], Is.TypeOf(typeof(MessageHeaderGeneratorComponent)));
            Assert.That(pipeline.PipelineComponents[2], Is.TypeOf(typeof(MessageFilterComponent)));
            Assert.That(pipeline.PipelineComponents[3],Is.TypeOf(typeof(MessageLoggingComponent)));
            Assert.That(pipeline.PipelineComponents[4], Is.TypeOf(typeof (LocalCallbackDispatcherComponent)));
            Assert.That(pipeline.PipelineComponents[5], Is.TypeOf(typeof (MessageHandlerDispatcherComponent)));


            MessagePipeline.ClearCurrentPipeline(PipelineDirection.Receive);
            Assert.That(pipeline.CurrentContext.MessageEnvelope,Is.SameAs(env));

            _endpoint.Stub(action => action.LocalServices).Return(_services);

            pipeline = factory.CreatePipelineFor(env, PipelineDirection.Send);
            Assert.That(pipeline.PipelineComponents.Count, Is.EqualTo(4));
            Assert.That(pipeline.PipelineComponents[0], Is.TypeOf(typeof(MessageHeaderGeneratorComponent)));
            Assert.That(pipeline.PipelineComponents[1], Is.TypeOf(typeof(MessageFilterComponent)));
            Assert.That(pipeline.PipelineComponents[2], Is.TypeOf(typeof(MessageLoggingComponent)));
            Assert.That(pipeline.PipelineComponents[3], Is.TypeOf(typeof (MessageBodySerializationComponent)));

            MessagePipeline.ClearCurrentPipeline(PipelineDirection.Send);
        }
    }
}
